#include <pio.h>
#include <std.h>
#define MONO 1
#include <error.h>

struct irq_handler	{
	void (*handler)();
	struct irq_handler *next;
}*head,*temp;

static unsigned long chain_base[16];
static unsigned int irq_flags[16];

void init_irq_chain()
{
	int i;
	for(i=0;i<16;i++)	{
		create_head(struct irq_handler,head);
		chain_base[i]=(unsigned long)head;
		irq_flags[i]=NULL;
	}
}

int chain_handler(int irq,void *handler)
{
	struct irq_handler *new;
	spin_lock chainirq;
	if(irq_flags[irq]==MONO)
		return -1;
	acquire_spin_lock(&chainirq);
	head=(struct irq_handler *)chain_base[irq];
	add_node_end(struct irq_handler,head,new);
	new->handler=handler;
	release_spin_lock(&chainirq);
}

int delete_handler(int irq,void *handler)
{
	struct irq_handler *head,*t;
	spin_lock delh;
	acquire_spin_lock(&delh);
	head=(struct irq_handler *)chain_base[irq];
	for(t=head;(t->handler)!=handler;t=t->next);
	delete_node(struct irq_handler,head,t);
	release_spin_lock(&delh);
}

int request_irq(int irq,void *handler)
{
	chain_handler(irq,handler);
	printf("\nIRQ grant:%d",irq);
	return NULL;
}

int release_irq(int irq,void *handler)
{
	delete_handler(irq,handler);
	printf("\nIRQ release:%d",irq);
	return NULL;
}

/*This function allows a device driver to have only itself hooked to the irq.*/
int request_irq_mono(int irq,void *handler)
{
	int i;
	i=chain_handler(irq,handler);
	printf("\nIRQ mono:%d",irq);
	if(i==-1)
		printf(":grant failed");
	return i;
}

void init_irq() 
{
	printf("\nStarting irq chain");
	init_8259();
	init_irq_chain();
}	


void uirq0()
{
	head=(struct irq_handler *)chain_base[0];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(0);
}

void uirq1()
{
	head=(struct irq_handler *)chain_base[1];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(1);
}

void uirq2()
{
	head=(struct irq_handler *)chain_base[2];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(2);
}

void uirq3()
{
	head=(struct irq_handler *)chain_base[3];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(3);
}

void uirq4()
{
	head=(struct irq_handler *)chain_base[4];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(4);
}

void uirq5()
{
	head=(struct irq_handler *)chain_base[5];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(5);
}

void uirq6()
{
	head=(struct irq_handler *)chain_base[6];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(6);
}

void uirq7()
{
	head=(struct irq_handler *)chain_base[7];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(7);
}

void uirq8()
{
 	head=(struct irq_handler *)chain_base[8];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(8);
}

void uirq9()
{
	head=(struct irq_handler *)chain_base[9];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(9);
}

void uirq10()
{
	head=(struct irq_handler *)chain_base[10];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(10);
}

void uirq11()
{
	head=(struct irq_handler *)chain_base[11];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(11);
}

void uirq12()
{
	head=(struct irq_handler *)chain_base[12];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(12);
}

void uirq13()
{
	head=(struct irq_handler *)chain_base[13];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(13);
}

void uirq14()
{
	head=(struct irq_handler *)chain_base[14];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(14);
}

void uirq15()
{
	head=(struct irq_handler *)chain_base[15];
	for(temp=head->next;temp!=NULL;temp=temp->next)	{
		(temp->handler)();
	}
	irq_ended(15);
}


